package com.ckk.eurekaclient.util;

import com.ckk.eurekaclient.exception.UnCheckedException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.apache.commons.lang.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author momo
 */
public class JsonUtil {

    /**
     * 构造器私有
     * <br/>
     * 决绝实例化
     */
    private JsonUtil() {

    }

    private static ObjectMapper mapper = new ObjectMapper()
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
            .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

    public static <T> T json2Obj(String jsonStr, Class<T> c) {
        if (StringUtils.isBlank(jsonStr)) {
            return null;
        }
        try {
            return mapper.readValue(jsonStr, c);
        } catch (Exception e) {
            e.printStackTrace();
            throw new UnCheckedException("序列化失败");
        }
    }

    public static <T> byte[] json2byte(T t) {
        if (t == null) {
            return new byte[0];
        }
        try {
            return mapper.writeValueAsBytes(t);
        } catch (Exception e) {
            e.printStackTrace();
            throw new UnCheckedException("序列化失败");
        }
    }

    public static String obj2Str(Object obj) {
        try {
            return mapper.writeValueAsString(obj);
        } catch (Exception e) {
            e.printStackTrace();
            throw new UnCheckedException("序列化失败");
        }
    }

    public static byte[] obj2Bytes(Object obj) {
        try {
            return mapper.writeValueAsBytes(obj);
        } catch (Exception e) {
            e.printStackTrace();
            throw new UnCheckedException("序列化失败");
        }
    }

    public static <K, V> Map<K, V> str2Map(String jsonStr, Class<K> k, Class<V> v) {
        try {
            JavaType javaType = mapper.getTypeFactory().constructParametricType(HashMap.class, k, v);
            return mapper.readValue(jsonStr, javaType);
        } catch (Exception e) {
            e.printStackTrace();
            throw new UnCheckedException("序列化失败");
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> List<T> objlist(Object obj, Class<T> t) {
        try {
            JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, t);
            return (List<T>) mapper.readValue(Objects.toString(obj), javaType);
        } catch (Exception e) {
            e.printStackTrace();
            throw new UnCheckedException("序列化失败");
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> List<T> json2List(String jsonStr, Class<T> t) {
        try {
            JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, t);
            return (List<T>) mapper.readValue(jsonStr, javaType);
        } catch (Exception e) {
            e.printStackTrace();
            throw new UnCheckedException("序列化失败");
        }
    }

    public static <K, V> Map<K, V> obj2Map(Object obj, Class<K> k, Class<V> v) {
        try {
            JavaType javaType = mapper.getTypeFactory().constructParametricType(HashMap.class, k, v);
            return mapper.readValue(mapper.writeValueAsBytes(obj), javaType);
        } catch (Exception e) {
            e.printStackTrace();
            throw new UnCheckedException("序列化失败");
        }
    }

    public static <T> T byte2json(byte[] bytes, Class<T> clz) {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        try {
            return mapper.readValue(bytes, clz);
        } catch (Exception e) {
            e.printStackTrace();
            throw new UnCheckedException("序列化失败");
        }
    }
}
